unit uLBSStateDB;

interface

uses
  SysUtils, Classes, SyncObjs, DB, ADODB, ActiveX,
  uDZDatabase, uGxtConfig, uGWCommonLog;

type
  TStateDB = class
  private
  	fLock: TSynchroObject;
    fConnection: TADOConnection;
    fQuery: TADOQuery;
  protected
    function CheckConnection: Boolean;
  public
    constructor Create;
    destructor Destroy; override;
    function GetState(const Phone: AnsiString): Integer;
    function SetState(const Phone: AnsiString; State: Integer): Boolean;  
  end;

function GetStateDB: TStateDB;

implementation

var
  StateDB: TStateDB;

function GetStateDB: TStateDB;
begin
  if StateDB = nil then StateDB := TStateDB.Create;
  Result := StateDB;
end;

{ TStateDB }

function TStateDB.CheckConnection: Boolean;
begin
  if fConnection.Connected then
  begin
    Result := True;
    Exit;
  end;
  fConnection.ConnectionString := GxtConfig.DBConnection.ConnString;
  fConnection.ConnectionTimeout := GxtConfig.DBConnection.ConnectionTimeout;
  try
    fConnection.Connected := True;
    Result := True;
  except
  	on e: Exception do 
  	begin 
  	  SendExceptionToDebugger('ConnectDB', e);
      Result := False;
    end;
  end;
end;

constructor TStateDB.Create;
begin
  fLock := TCriticalSection.Create;
  fConnection := TADOConnection.Create(nil);
  fConnection.ConnectionString := GxtConfig.DBConnection.ConnString;
  fConnection.LoginPrompt := False;
  fConnection.ConnectionTimeout := GxtConfig.DBConnection.ConnectionTimeout;
  fQuery := TADOQuery.Create(fConnection);
  fQuery.Connection := fConnection;
  fQuery.CommandTimeout := GxtConfig.DBConnection.CommandTimeout;
end;

destructor TStateDB.Destroy;
begin
  fConnection.Free;
  fLock.Free;
  inherited;
end;

function TStateDB.GetState(const Phone: AnsiString): Integer;
begin
  Result := -1;
  fLock.Acquire;
  try
    if not CheckConnection then Exit;
    fQuery.SQL.Text := WideFormat('select Status from LBSStatus ' +
      'where PhoneNumber = ''%s''', [WideString(Phone)]);
    while True do
    try
      fQuery.Active := True;
      if fQuery.IsEmpty then Result := 0
      else Result := fQuery.Fields[0].AsInteger;
      Break;
    except
      on E: Exception do
      begin
        SendExceptionToDebugger('OpenDBQuery', E);
        if CanReConnect(E.Message) then
        begin
          fConnection.Connected := False;
          if (not CheckConnection) then Break;
        end
        else Break;
      end;
    end;
  finally
    fLock.Release;
  end;
end;

function TStateDB.SetState(const Phone: AnsiString; State: Integer): Boolean;
begin	
  Result := False;
  fLock.Acquire;
  try
    if not CheckConnection then Exit;
    fQuery.SQL.Text := WideFormat('select PhoneNumber, Status, UpdateTime ' +
    'from LBSStatus where PhoneNumber = ''%s''', [WideString(Phone)]);
    while True do
    try
      fQuery.Open;
      if fQuery.IsEmpty then
      begin
        fQuery.Insert;
        fQuery.Fields[0].Value := Phone;
      end
      else fQuery.Edit;
      fQuery.Fields[1].Value := Ord(State);
      fQuery.Fields[2].Value := Now;
      fQuery.Post;
      Result := True;
      Break;
    except
      on E: Exception do
      begin
        SendExceptionToDebugger('TStateDB.SetState', E);
        if CanReConnect(E.Message) then
        begin
          fConnection.Connected := False;
          if not CheckConnection then Break;
        end
        else Break;
      end;
    end;
  finally
    fLock.Release;
  end;
end;

initialization
  ActiveX.CoInitialize(nil);

finalization
  if StateDB <> nil then StateDB.Free;
  ActiveX.CoUninitialize;
  
end.
